/*
  Copyright 2006 by Sean Luke and George Mason University
  Licensed under the Academic Free License version 3.0
  See the file "LICENSE" for more information
*/

package sim.app.networktest;

import java.awt.Color;
import java.awt.Font;
import java.awt.Graphics2D;
import java.awt.geom.Ellipse2D;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.ObjectOutputStream;
import java.util.HashMap;

import javax.swing.JOptionPane;

import sim.engine.SimState;
import sim.engine.Steppable;
import sim.portrayal.DrawInfo2D;
import sim.portrayal.SimplePortrayal2D;
import sim.util.Double2D;
import ventureco.agent.AgentImpl;
import ventureco.communication.AgentMessage;
import ventureco.communication.ThreadClient;
import ventureco.communication.ThreadServer;
import ventureco.task.Task;

public /*strictfp*/ class CustomNode extends SimplePortrayal2D implements Steppable
    {

	/**
	 * 
	 */
	private static final long serialVersionUID = 1L;
	public Task task;
    public String id;
    public static int port;
    public static HashMap<Integer, Integer> ipAddresses = new HashMap<Integer, Integer>();
    public String getID() { return id; }
    public void setID( final String id ) { this.id = id; }
    public double getX(){return desiredLocation.getX();}
    public double getY(){return desiredLocation.getY();}

    public CustomNode( String id, int port)
        {
    	CustomNode.port = port;
        this.id = id;
        
    	ThreadServer thserver = new ThreadServer(port);
    	thserver.start();

    	
    	byte lasttwo = (byte) (port - 5500);
    	byte[] lasttwo2 = {lasttwo};

    	ThreadClient thclient = new ThreadClient("localhost", 6666, lasttwo2,1);
    	thclient.start();
    	
    	try {
    		Thread.sleep(200);
    	} catch (InterruptedException e) {}	
        }

    Double2D desiredLocation = new Double2D();// = null;
    Double2D suggestedLocation = new Double2D(); // null;
    int steps = 0;
    int sagsol = 1; 
    int ustalt = 1;
    
    
    public void step( final SimState state )
        {
        NetworkTest nt = (NetworkTest)state;
        Double2D location = nt.environment.getObjectLocation(this);
        
        int nodesize = nt.network.allNodes.size();
        AgentImpl agent = new AgentImpl();
        int ind = 0;
        int slowestAgentInd = 0;
        int tempVel = 0;
        for(int i =0; i < agent.getAgentCount();i++){
        	
        	
        	if(id.equalsIgnoreCase("Agent-"+agent.getList().get(i).getID())){
        		
        		ind = i;
        		break;
        	}
        	
        	
        }
        for(int i =0; i < agent.getAgentCount();i++){
        	
        	if(agent.getList().get(i).getMaxVelocity()>tempVel){
        		tempVel = (int) agent.getList().get(i).getMaxVelocity();
        		slowestAgentInd = i;
        	}
        	
        }
        steps--;
         
        
        if( desiredLocation == null || steps <= 0 )
            {
//            desiredLocation = new Double2D((state.random.nextDouble()-0.5)*((NetworkTest.XMAX-NetworkTest.XMIN)/5-NetworkTest.DIAMETER) + location.x,
//                (state.random.nextDouble()-0.5)*((NetworkTest.YMAX-NetworkTest.YMIN)/5-NetworkTest.DIAMETER) + location.y);
        	
        	
        	if(location.x + ((NetworkTest.XMAX-NetworkTest.XMIN)/10-NetworkTest.DIAMETER)*sagsol >= this.task.bottomRight.x){
        		

        		if(location.y + ((NetworkTest.YMAX-NetworkTest.YMIN)/10-NetworkTest.DIAMETER)*ustalt <= this.task.bottomLeft.y){
            		
            		location.y = location.y + ((NetworkTest.YMAX-NetworkTest.YMIN)/10-NetworkTest.DIAMETER)  ;
            		ustalt = 1;
            		if(id.equalsIgnoreCase("Agent-"+agent.getList().get(slowestAgentInd).getID())){
            			JOptionPane.showMessageDialog(null, "Agents accomplished patrolling entire area, and resuming scanning.");
            		}
            	}else if(location.y + ((NetworkTest.YMAX-NetworkTest.YMIN)/10-NetworkTest.DIAMETER)*ustalt >= this.task.topLeft.y){
            		
            		location.y = location.y - ((NetworkTest.YMAX-NetworkTest.YMIN)/10-NetworkTest.DIAMETER);
            		ustalt = -1;
            		
            		
            	}else{
            		location.y = (((NetworkTest.YMAX-NetworkTest.YMIN)/10-NetworkTest.DIAMETER)/5)*ustalt + location.y;
            		sagsol = -1;
            	}
        	
        	}else if(location.x + ((NetworkTest.XMAX-NetworkTest.XMIN)/10-NetworkTest.DIAMETER)*sagsol <= this.task.bottomLeft.x){
        		if(location.y + ((NetworkTest.YMAX-NetworkTest.YMIN)/10-NetworkTest.DIAMETER)*ustalt <= this.task.bottomLeft.y){
            		
            		location.y = location.y + ((NetworkTest.YMAX-NetworkTest.YMIN)/10-NetworkTest.DIAMETER)  ;
            		ustalt = 1;
            		if(id.equalsIgnoreCase("Agent-"+agent.getList().get(slowestAgentInd).getID())){
            			JOptionPane.showMessageDialog(null, "Agents accomplished patrolling entire area, and resuming scanning.");
            		}
            	}else if(location.y + ((NetworkTest.YMAX-NetworkTest.YMIN)/10-NetworkTest.DIAMETER)*ustalt >= this.task.topLeft.y){
            		
            		
            		location.y = location.y - ((NetworkTest.YMAX-NetworkTest.YMIN)/10-NetworkTest.DIAMETER);
            		ustalt = -1;
            		
            	}else{
        		location.y = (((NetworkTest.YMAX-NetworkTest.YMIN)/10-NetworkTest.DIAMETER)/5)*ustalt + location.y;
        		sagsol = 1;}
        	}
        	//JOptionPane.showMessageDialog(null, agent.getList().get(ind).getMaxVelocity());
        	desiredLocation = new Double2D(location.x + ((NetworkTest.XMAX-NetworkTest.XMIN)/5-NetworkTest.DIAMETER)*sagsol , location.y);
//            steps = 50+state.random.nextInt(50);
        	
        	
        	steps = (int)(agent.getList().get(ind).getMaxVelocity()/2);
//        	if(steps == 14){
//        		steps = 55;
//        		
//        	}else if (steps == 21){
//        		steps = 52;
//        	}else if(steps == 20){
//        		steps = 50;
//        	}else if(steps == 37){
//        		steps = 48;
//        	}else if(steps == 60){
//        		steps = 46;
//        		
//        	}
 //       	steps = 50;
//        	if(steps < 50){
//        		steps = 50;
//        	}
            }

        double dx = desiredLocation.x - location.x;
        double dy = desiredLocation.y - location.y;
//        System.out.println("node Id :" + this.id + "     xPosition : " + dx + "     yPosition: " + dy);

                {
                double temp = /*Strict*/Math.sqrt(dx*dx+dy*dy);
                if( temp < 1 )
                    {
                    steps = 0;
                    }
                else
                    {
                    dx /= temp;
                    dy /= temp;
                    }
                }

        if( ! nt.acceptablePosition( this, new Double2D( location.x + dx, location.y + dy ) ) )
            {
            steps = 0;
            }
        else
            {
            nt.environment.setObjectLocation(this, new Double2D(location.x + dx, location.y + dy));
            }

        }

    public Font nodeFont = new Font("SansSerif", Font.PLAIN, 12);
    
    public final void draw(Object object, Graphics2D graphics, DrawInfo2D info)
        {
        double diamx = info.draw.width*NetworkTest.DIAMETER;
        double diamy = info.draw.height*NetworkTest.DIAMETER;

        graphics.setColor( Color.red );
        graphics.fillOval((int)(info.draw.x-diamx/2),(int)(info.draw.y-diamy/2),(int)(diamx),(int)(diamy));
        graphics.setFont(nodeFont.deriveFont(nodeFont.getSize2D()*(float)info.draw.width));
        graphics.setColor( Color.blue );
        graphics.drawString( id, (int)(info.draw.x-diamx/2), (int)(info.draw.y-diamy/2) );
        }

    public boolean hitObject(Object object, DrawInfo2D info)
        {
        double diamx = info.draw.width*NetworkTest.DIAMETER;
        double diamy = info.draw.height*NetworkTest.DIAMETER;

        Ellipse2D.Double ellipse = new Ellipse2D.Double( (int)(info.draw.x-diamx/2),(int)(info.draw.y-diamy/2),(int)(diamx),(int)(diamy) );
        return ( ellipse.intersects( info.clip.x, info.clip.y, info.clip.width, info.clip.height ) ); 
        }
    
    public static void sendMess(int agentCount, int i) {

//    	System.out.println(port+"  " + NetworkTest.portNumber);
    	if(port == NetworkTest.portNumber-1) {
//    		String hostname = "localhost";
//    		byte[] data = "VENTURE CO...".getBytes();
//    		

			try {
    			Thread.sleep(5000);
    		} catch (InterruptedException e) {}	
    
			
		/*	
			for (int i = 0; i < agentCount-1;i++) {
//    			portFirst++;
    			port--;
    			//sendMessage
    			byte[] pureDataToSend = new byte[data.length + 1];
    			pureDataToSend[0] = 1;
    			System.arraycopy(data, 0, pureDataToSend, 1, data.length);
    			
    			ThreadClient thclient = new ThreadClient(hostname,port, pureDataToSend,1);
    			thclient.start();
				
			}
			*/
			
			
			AgentMessage message = new AgentMessage();
			if(i==1)message.setTaskIsTaken(true);
			else if(i==2) message.setTaskIsFailed(true);
			else if(i==3) message.setTaskComplated(true);
			else if(i==4) message.setNewTasks(true);
			else if(i==5) message.setAllArea(true);
			
			ByteArrayOutputStream baos = new ByteArrayOutputStream();
			ObjectOutputStream objout;
			try {
				objout = new ObjectOutputStream(baos);
				objout.writeObject(message);
			} catch (IOException e) {
				
				e.printStackTrace();
			}
			byte[] dataToSend = baos.toByteArray();
			
			byte[] pureDataToSend = new byte[dataToSend.length + 1];
			pureDataToSend[0] = 1;
			System.arraycopy(dataToSend, 0, pureDataToSend, 1, dataToSend.length);
			
			ThreadClient threadclient = new ThreadClient("localhost", 5555, pureDataToSend,0);
			threadclient.start();
    	}
    	
    }
    
    public static final byte[] intToByteArray(int value) {
        return new byte[] {
                (byte)(value >>> 8),
                (byte)value};
    }
    
   

    }
